package main;

import java.io.*;

public class IO {
	private IOController ioController;
	private GameController gameController;
	
	private InputStream inputStream;
	private PrintStream printStream;
	
	//default constructor
	public IO(){
		setIOStream(System.in, System.out);
		initSystem();
	}
	
	//constructor
	/*
	 * @param	inputStream	input stream which provide all inputs to the system
	 * @param	printStream	print stream which accept all output of the system
	 */
	public IO(InputStream inputStream, PrintStream printStream){
		setIOStream(inputStream, printStream);
		initSystem();
	}
	
	
	//set streams
	/*
	 * @param	inputStream	input stream which provide all inputs to the system
	 * @param	printStream	print stream which accept all output of the system
	 */
	private void setIOStream(InputStream inputStream, PrintStream printStream){
		this.inputStream = inputStream;
		this.printStream = printStream;
	}
	
	//init IOController
	//init GameController
	/*
	 * @see	IOController
	 * @see	GameController
	 */
	private void initSystem(){
		ioController = new IOController(this);
		gameController = new GameController(ioController);
	}
	
	//click start the game
	public void startGame(){
		gameController.startGame();
	}
	
	//get input from input stream by showing the input hints
	/*
	 * @param	inputHints	string to be showed to instruct the users to input the wanted information
	 */
	public int getInput(String inputHints){
		int inputValue = -1;
		boolean isCorrect = true;
		do{
			isCorrect = true;
			
			showMsg("Please input " + inputHints + ": ");
			InputStreamReader isReader = new InputStreamReader(inputStream);
			BufferedReader bufferedReader = new BufferedReader(isReader);
			try{
				inputValue = Integer.parseInt(bufferedReader.readLine(), 10);
			}
			catch (NumberFormatException err){
				isCorrect = false;
				printStream.println("Input only one integers within the range.");
			}
			catch (IOException err){
				isCorrect = false;
				printStream.println("IO error, please try again.");
			}
		}while(!isCorrect);
		return inputValue;
	}
	
	//print the field to print stream
	/*
	 * @param	field	2-D char array storing the symbolic form of the field, which ready to be showing
	 * @param	width	field width
	 * @param	height	field height
	 */
	public void  showField(char[][] field, int width, int height) {
		printStream.printf("\n\n\n\n");
		printStream.printf("  ");
		for(int j = 0; j < width; j ++)
			printStream.printf(".%d", j);
		printStream.printf(".\n");
		
		for(int i = 0; i < height; i ++){
			printStream.printf("  ");
			for(int j = 0; j < width; j ++)
				printStream.printf("--");
			printStream.printf("-\n");
			printStream.printf("%d>", i);
			
			for(int j = 0; j < width; j ++)
				printStream.printf("|%c", field[i][j]);
			printStream.printf("|\n");
		}
		
		printStream.printf("  ");
		for(int j = 0; j < width; j ++)
			printStream.printf("--");
		printStream.printf("-\n");
		
	}
	
	//print specific msg to print stream
	/*
	 * @param	msg	the message (without modification) to be shown to the user
	 */
	public void showMsg(String msg){
		printStream.print(msg);
	}
	
	//propagate the input values to subsequence object(s)
	/*
	 * @param	x	inputed x-coordinate
	 * @param	y	inputed y-corrdinate
	 */
	public void propagateInput(int x, int y){
		gameController.process(x, y);
	}
}
